home *** CD-ROM | disk | FTP | other *** search
- /* File: codrle2.c
- Author: David Bourgin
- Creation date: 1/2/94
- Last update: 24/7/95
- Purpose: Example of RLE type 2 encoding with a file source to compress.
- */
-
- #include <stdio.h>
- /* For routines printf,fgetc,fputc and rewind */
- #include <memory.h>
- /* For routine memset */
- #include <stdlib.h>
- /* For routine exit */
-
- /* Error codes sent to the caller */
- #define NO_ERROR 0
- #define BAD_FILE_NAME 1
- #define BAD_ARGUMENT 2
-
- /* Useful constants */
- #define FALSE 0
- #define TRUE 1
-
- /* Global variables */
- FILE *source_file,*dest_file;
-
- /* Being that fgetc=EOF only after an access
- then 'byte_stored_status' is 'TRUE' if a byte has been stored by 'fgetc'
- or 'FALSE' if there's no valid byte not already read and not handled in 'val_byte_stored' */
- int byte_stored_status=FALSE;
- int val_byte_stored;
-
- /* Pseudo procedures */
- #define beginning_of_data() (byte_stored_status=FALSE,(void)rewind(source_file))
- #define end_of_data() (byte_stored_status?FALSE:!(byte_stored_status=((val_byte_stored=fgetc(source_file))!=EOF)))
- #define read_byte() (byte_stored_status?byte_stored_status=FALSE,(unsigned char)val_byte_stored:(unsigned char)fgetc(source_file))
- #define write_byte(byte) ((void)fputc((byte),dest_file))
-
- void rle2write_rep(header_byte,repeated_byte,repetition_number)
- /* Returned parameters: None
- Action: Writes in the output compression stream the encoding of 'repetition_number' times 'repeated_byte'.
- 'header_byte' is used as marker as defined in RLE 2 method
- Errors: An input/output error could disturb the running of the program
- */
- unsigned char header_byte,repeated_byte;
- unsigned int repetition_number;
- { if (repetition_number<4)
- if (repeated_byte==header_byte)
- { write_byte(header_byte);
- write_byte(repetition_number-1);
- }
- else { register unsigned int i;
-
- for (i=1;i<=repetition_number;i++)
- write_byte(repeated_byte);
- }
- else { write_byte(header_byte);
- write_byte(repetition_number-1);
- write_byte(repeated_byte);
- }
- }
-
- void rle2write_non_rep(header_byte,non_repeated_byte)
- /* Returned parameters: None
- Action: Writes in the output compression stream the encoding of 'non_repeated_byte'
- 'header_byte' is used as marker as defined in RLE 2 method
- Errors: An input/output error could disturb the running of the program
- */
- unsigned char header_byte,non_repeated_byte;
- { if (non_repeated_byte==header_byte)
- { write_byte(header_byte);
- write_byte(0);
- }
- else write_byte(non_repeated_byte);
- }
-
- void rle2encoding()
- /* Returned parameters: None
- Action: Compresses with RLE type 2 method all bytes read by the function read_byte
- Errors: An input/output error could disturb the running of the program
- */
- { unsigned char byte1,byte2,header_byte;
- unsigned int frame_size;
- register unsigned int i;
- unsigned long int lookup_table[256];
-
- if (!end_of_data()) /* Is there at least a byte to analyze? */
- { /* Sets up the occurrence numbers of all bytes to 0 */
- (void)memset((char *)lookup_table,0,sizeof(lookup_table));
- /* This is the same to fill 'lookup_table' to 0.
- It's fastest than to loop 256 times */
- while (!end_of_data())/* Valids the occurrences in 'lookup_table' in regard to the data to compress */
- { byte1=read_byte();
- lookup_table[byte1]++;
- }
- header_byte=0;
- for (i=1;i<=255;i++)
- if (lookup_table[i]<lookup_table[header_byte])
- header_byte=i;
- write_byte(header_byte);
- beginning_of_data(); /* New data analysis */
- byte1=read_byte();
- frame_size=1;
- if (!end_of_data())
- /* Are there at least two bytes? */
- { byte2=read_byte();
- frame_size=2;
- do { /* Real beginning of the compression */
- if (byte1==byte2)
- /* Do we meet only a sequence of identical bytes? */
- { while ((!end_of_data())&&(byte1==byte2)&&(frame_size<256))
- { byte2=read_byte();
- frame_size++;
- }
- if (byte1==byte2)
- { rle2write_rep(header_byte,byte1,frame_size);
- if (!end_of_data())
- { byte1=read_byte();
- frame_size=1;
- }
- else frame_size=0;
- }
- else { rle2write_rep(header_byte,byte1,frame_size-1);
- byte1=byte2;
- frame_size=1;
- }
- }
- else { /* No, then don't handle the last byte */
- rle2write_non_rep(header_byte,byte1);
- byte1=byte2;
- frame_size=1;
- }
- if (!end_of_data())
- { byte2=read_byte();
- frame_size=2;
- }
- }
- while ((!end_of_data())||(frame_size>=2));
- }
- if (frame_size==1) /* Was there a last byte to analyze? */
- rle2write_non_rep(header_byte,byte1);
- }
- }
-
- void help()
- /* Returned parameters: None
- Action: Displays the help of the program and then stops its running
- Errors: None
- */
- { printf("This utility enables you to compress a file by using RLE type 2 method\n");
- printf("as given in 'La Video et Les Imprimantes sur PC'\n");
- printf("\nUse: codrle2 source target\n");
- printf("source: Name of the file to compress\n");
- printf("target: Name of the compressed file\n");
- }
-
- int main(argc,argv)
- /* Returned parameters: Returns an error code (0=None)
- Action: Main procedure
- Errors: Detected, handled and an error code is returned, if any
- */
- int argc;
- char *argv[];
- { if (argc!=3)
- { help();
- exit(BAD_ARGUMENT);
- }
- else if ((source_file=fopen(argv[1],"rb"))==NULL)
- { help();
- exit(BAD_FILE_NAME);
- }
- else if ((dest_file=fopen(argv[2],"wb"))==NULL)
- { help();
- exit(BAD_FILE_NAME);
- }
- else { rle2encoding();
- fclose(source_file);
- fclose(dest_file);
- }
- printf("Execution of codrle2 completed.\n");
- return (NO_ERROR);
- }
-